<?php

use App\Models\Category;
use App\Models\Invitation;
use App\Models\Message;
use App\Models\Tag;
use App\Models\User;
use App\Services\AuthService;
use App\Services\Event;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Route;

/**
 * API for MVC
 */
Route::get('/search-users',function (Request $request){
    $name = $request->input('name');
    $event_id = $request->input('event_id');
    $event = Event::find($event_id);
    $filtered_users = User::where('name', 'like', '%'.$name.'%')
        ->whereNot('id',Auth::id())->get();
    $users = $filtered_users->filter(fn($user) => !$user->hasInvitation($event))->flatten();
    return response(["users"=>$users]);
});

Route::post("/invitations",function (Request $request){
    if(!Auth::check()) return response(["error"=>"unauthorized"], 401);
    try{
        DB::transaction(function() use($request){
            $inv = Invitation::create($request->all());

            $event = Event::find($request->input('event_id'));
            $message = Message::create([
                "sender_id" => Auth::id(),
                "receiver_id" => $request->user_id,
                "content"=>"You have been invited to join ".$event->title .". Click the link to see the event detail."
            ]);
            if(!$inv || !$message){
                throw new Exception("Invitation not created");
            }
        });
    }catch (Exception $e){
        return response()->json([
            "msg" => "Invitation not sent!",
        ],500);
    }
    return response()->json([
        "msg" => "Invitation sent!",
    ],200);

});

Route::get("/join-event",function (Request $request){
    if(!Auth::check()) return response(["error"=>"unauthorized"], 401);
    $user = Auth::user();
    $event_id = $request->input('event_id');
    $event = Event::find($event_id);
    if(!$event){
        return response()->json(["msg"=>"Object not found!"],404);
    }
    $user->joinedEvents()->attach($event);
    return response([
        "msg" => "Joined!",
        "name"=>Auth::user()->name
    ],200);
});


/**
 * MVC Routes
 */

Route::get('/', function () {
    return view('home');
});

Route::get('/login',function(){
    return view('login');
});

Route::post('/login',function (Request $request, AuthService $authService){
    $user = $authService->login($request->all());
    if($user){
        Auth::login($user,true);
        $request->session()->regenerate();
        return redirect("/");
    }
    return redirect('/login');
});

Route::get('/logout',function(){
    Auth::logout();
    return redirect('/');
});

Route::get('/events',function(){
    $events = Event::all();
    $tags = Tag::orderBy('name')->get();
    $categories = Category::orderBy('name')->get();
    return view('events',compact('events','tags','categories'));
});

Route::get('/new-event',function(){
    if(!Gate::allows('create-event')){
        return redirect('/events');
    }
    return view('new-event');
});


Route::post('/new-event',function(Request $request){
    if(!Gate::allows('create-event')){
        return redirect('/events');
    }
    //dd($request->start_at);
    $v = \Illuminate\Support\Facades\Validator::make($request->all(),[
        'title' => 'required',
        'description' => 'sometimes|string',
        'location' => 'required|string',
        'capacity' => 'required|integer',
        'type'=>'in:PUBLIC,PRIVATE',
        'start_at'=>"required|date",
        'end_at'=>"required|date|after:start_at",
        'tags'=>"sometimes|array",
        'category'=>"required|string",
    ]);
    if(!$v->fails()){
        try{
            DB::transaction(function() use($request,$v){
                $category = Category::firstOrCreate(["name"=>ucfirst($request->category)]);
                if(!$category) throw new Exception("Failed to create category");
                $request->merge(["category_id"=>$category->id]);
                $request->merge(["creator_id"=>Auth::id()]);
                $event = Event::create($request->except(['tags','category']));
                if(!$event) throw new Exception("Failed to create event");
                $tags_id = [];
                foreach ($request->get('tags') as $tag){
                    $tag = Tag::firstOrCreate(["name"=>$tag]);
                    if(!$tag) throw new Exception("Failed to create tag");
                    $tags_id[] = $tag->id;
                }
                $event->tags()->sync($tags_id);
                $event->participants()->sync(Auth::id());
            });
        }catch (Exception $exception){
            return redirect()->back()->withInput()->with(["tags"=>$request->get("tags")]);
        }
        return redirect("/events");
    }
    return redirect()->back()->withErrors($v->errors())->withInput()->with(["tags"=>$request->get("tags")]);
});


Route::get('/events/{id}',function($id){
    $event = Event::find($id);
    if(!$event) return "<h1>Object not found!</h1>";
    $users = User::orderBy('name')->get();
    return view('event-detail',compact('event',"users"));
});
